package com.zpself.分布式锁.redisson;

import org.junit.Test;
import org.redisson.Redisson;
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * @author By ZengPeng
 * @Description 100个线程抢 10个物品，是否会出现超卖
 * @date in  2021/3/13 23:15
 * @Modified By
 */
public class redisson分析 {
    private static int inventory = 10;

    public static void main(String[] args) throws InterruptedException {
        //初始化线程池
        LinkedBlockingQueue<Runnable> linkedBlockingQueue = new LinkedBlockingQueue<>(100);//实际执行线程数
        ThreadPoolExecutor threadPoolExecutor =
                new ThreadPoolExecutor(inventory, inventory, 10L, SECONDS, linkedBlockingQueue);

        //初始化连接池
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        final RedissonClient client = Redisson.create(config);
        final RLock lock = client.getLock("lock1");


        CountDownLatch cd = new CountDownLatch(1);  //来个线程发起器
        CountDownLatch over = new CountDownLatch(1);//抢完了
        //实际执行线程数
        int NUM = 11;
        //创建线程开始了
        for (int i = 0; i < NUM; i++) {
            threadPoolExecutor.execute(() -> {
                try {
                    cd.await();//等待开始

                   // lock.lock(2,TimeUnit.SECONDS);

                    lock.lock();
                    if(inventory<=0){
                        over.countDown();
                        return;
                    }
                    inventory--;
                    System.out.println("线程："+Thread.currentThread()+"抢占成功！还剩下："+inventory);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            });
        }
        long start = System.currentTimeMillis();
        cd.countDown();

        over.await();
        long end = System.currentTimeMillis();
        System.out.println("执行线程数:" + NUM + "   总耗时:" + (end - start) + "  库存剩余数为:" + inventory);

        //关闭线程池
        System.out.println("1正在活跃线程数："+ threadPoolExecutor.getActiveCount());
        threadPoolExecutor.shutdown();
        //等待未抢到的线程执行完   比这个好用噢：Thread.sleep(2000);
        if(threadPoolExecutor.awaitTermination(2, TimeUnit.SECONDS))
            System.out.println("线程池任务已全部完成！");
        System.out.println("2正在活跃线程数："+ threadPoolExecutor.getActiveCount());

        //关闭Redisson连接池
        client.shutdown();
    }


    @Test
    public void test() {
        //初始化连接池
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        final RedissonClient client = Redisson.create(config);
        final RLock lock = client.getLock("lock1");

        //lock.lock(5,TimeUnit.SECONDS);//到期自动释放
        lock.lock();//无租期，默认30秒，每1/3=10秒更新锁的超时时间
        lock.unlock();//无租期，默认30秒，每1/3=10秒更新锁的超时时间
       // CountDownLatch cd  =new CountDownLatch(1);
        LockSupport.parkNanos(60*1000*1000000L);

    }

    //--------------------------- 主从节点切换丢失 ---------------------------
    @Test
    public void test2() {
        //初始化连接池 1
        Config config1 = new Config();
        config1.useSingleServer().setAddress("redis://127.0.0.1:6379");
        final RedissonClient client1 = Redisson.create(config1);

        //初始化连接池 2
        Config config2 = new Config();
        config2.useSingleServer().setAddress("redis://127.0.0.1:6380");
        final RedissonClient client2 = Redisson.create(config2);

        //初始化连接池 2
        Config config3 = new Config();
        config3.useSingleServer().setAddress("redis://127.0.0.1:6380");
        final RedissonClient client3 = Redisson.create(config3);

        //无关联的 Node 组成一个完整的分布式锁  --【红锁】
        String lockKey= "lock1";
        RLock lock = Redisson.create(config1).getLock(lockKey+"1");
        RLock lock2 = Redisson.create(config2).getLock(lockKey+"2");
        RLock lock3 = Redisson.create(config3).getLock(lockKey+"3");
        lock.lock();
        RedissonRedLock redLock = new RedissonRedLock(lock, lock2, lock3);

        try {

            RLock lockStr = Redisson.create(config1).getLock("lock12345");
            boolean b = lockStr.tryLock(100000,30, SECONDS);
            boolean b1 = lockStr.tryLock(100000, SECONDS);
            boolean b2 = lockStr.tryLock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        redLock.unlock();
    }
}
